﻿using System;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace TestByWire.Test
{
    [TestClass]
    public class WhenTests
    {
        private object _sender;
        private EventArgs _eventArgs;
        private Boolean _called;

        [TestInitialize]
        public void Init()
        {
            _called = false;
            _sender = null;
            _eventArgs = null;
        }

        [TestMethod]
        public void ShouldRaiseEvent()
        {
			new TargetInvokerUnderTest(typeof(MyType));
            When<IEventRaiser>.RaiseEvent(x => x.myEvent += OnEvent, With<IEventRaiser>.Dependency, null);

            Assert.IsTrue(_called);
            Assert.IsInstanceOfType(_sender, typeof(IEventRaiser));
            Assert.AreEqual(null, _eventArgs);
        }

        [TestMethod]
        public void ShouldTransferToTestTarget()
        {
			new TargetInvokerUnderTest(typeof(MyType));

            When<IEventRaiser>.RaiseEvent(x => x.myEvent += OnEvent, this, EventArgs.Empty);

            Assert.IsNotNull(Then.Target);
        }

        [TestMethod]
        public void ShouldRaiseEventWithParameters()
        {
			new TargetInvokerUnderTest(typeof(MyType));

            var expectedArgs = new EventArgs();
            When<IEventRaiser>.RaiseEvent(x => x.myEvent += OnEvent, With<IEventRaiser>.Dependency, expectedArgs);

            Assert.IsTrue(_called);
            Assert.IsInstanceOfType(_sender, typeof(IEventRaiser));
            Assert.AreEqual(expectedArgs, _eventArgs);
        }

        [TestMethod]
        public void ShouldRaiseNamedStub()
        {
			new TargetInvokerUnderTest(typeof(MyType));
            TargetInvoker.Container.RegisterInstance("namedStub", With<IEventRaiser>.Dependency);

            When<IEventRaiser>.RaiseEvent("namedStub", x => x.myEvent += OnEvent, With<IEventRaiser>.Dependency, EventArgs.Empty);

            Assert.IsTrue(_called);
            Assert.IsInstanceOfType(_sender, typeof(IEventRaiser));
            Assert.AreEqual(EventArgs.Empty, _eventArgs);
        }

        [TestMethod]
        public void ShouldRaiseInternalEventHandler()
        {
			new TargetInvokerUnderTest(typeof(MyTypeWithInternalEventHandler));

            When<IEventRaiser>.RaiseEvent(x => x.myEvent += null, this, EventArgs.Empty);

            Assert.IsTrue(((MyTypeWithInternalEventHandler)Then.Target).MyEventHandlerInvoked);
        }

        private void OnEvent(object sender, EventArgs eventArgs)
        {
            _called = true;
            _sender = sender;
            _eventArgs = eventArgs;
        }
    }

    public class MyType
    {
    }

    public class MyTypeWithInternalEventHandler
    {
        public MyTypeWithInternalEventHandler(IEventRaiser eventRaiser)
        {
            eventRaiser.myEvent += MyEventHandler;
            MyEventHandlerInvoked = false;
        }

        public bool MyEventHandlerInvoked { get; set; }

        void MyEventHandler(object sender, EventArgs e)
        {
            MyEventHandlerInvoked = true;
        }
    }

    public interface IEventRaiser
    {
        event EventHandler myEvent;
    }
}
